/**
 * 文件名：****.java
 * 版权：Copyright Lightkit All Rights Reserved.
 * 描述：*****
 */
package com.lightkits.wms.domain.deliveryticket.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lightkits.common.TransactionValidate;
import com.lightkits.common.db.entity.FndDocumentTypeBase;
import com.lightkits.common.db.entity.FndItemBase;
import com.lightkits.common.db.entity.FndOrganizationBase;
import com.lightkits.common.db.entity.FndWarehouse;
import com.lightkits.common.db.entity.FndWorker;
import com.lightkits.common.db.entity.WmDeliveryTicket;
import com.lightkits.common.db.entity.WmDeliveryTicketLine;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.logging.Logger;
import com.lightkits.framework.common.logging.LoggerFactory;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.json.JsonUtil;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.common.utility.object.ParseUtil;
import com.lightkits.framework.common.utility.validate.IntegrityValidator;
import com.lightkits.wms.domain.deliveryticket.service.SaveTicketLineDomain;
import com.lightkits.wms.domain.rawmatstorage.repo.WmDeliveyTicketLineService;
import com.lightkits.wms.domain.stocktransfer.service.MiscellAdjustDomain;
import com.lightkits.wms.domain.usuallyinterface.GetWmMoveTypeExecutor;
import com.lightkits.wms.dto.deliveryticket.models.TicketLineDTO;
import com.lightkits.wms.dto.stocktransfer.model.MiscellAdjust;
import com.lightkits.wms.util.models.LineControl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 送货单行创建
 *
 * @author jing.wei@hand-china.com
 * Created on 2019/4/23 14:38
 */
@Service
public class SaveTicketLineDomainImpl implements SaveTicketLineDomain {
    private final Logger logger = LoggerFactory.getLogger(GetWmMoveTypeExecutor.class);
    private final WmDeliveyTicketLineService wmDeliveyTicketLineService;

    private final MiscellAdjustDomain miscellAdjustDomain;

    @Autowired
    public SaveTicketLineDomainImpl(WmDeliveyTicketLineService wmDeliveyTicketLineService,
                                    MiscellAdjustDomain miscellAdjustDomain) {
        this.wmDeliveyTicketLineService = wmDeliveyTicketLineService;
        this.miscellAdjustDomain = miscellAdjustDomain;
    }

    /**
     * 送货单行参数校验
     *
     * @param dtos     送货单行参数
     * @param ticketId 送货单头ID
     * @return IResult
     */
    private IResult checkParams(List<TicketLineDTO> dtos, String ticketId) {
        try {
            //参数必输校验
            IntegrityValidator.begin().validate(ticketId, "Ticket Id");
//参数有效性校验
            TransactionValidate check = TransactionValidate.beginValidity(WmDeliveryTicket.class);
            check.checkIdValidity(ObjectUtil.toString(ticketId), "ID");
            //行参数校验
            dtos.forEach(dto -> {
                //行参数必输校验
                IntegrityValidator.begin()
                        .validate(dto.getItemId(), "Item Id")
                        .validate(dto.getReceiveQty(), "Receive Quantity")
                        .validate(dto.getOrgId(), "Organization Id")
                        .validate(dto.getReceiveWorkerId(), "Receive Worker Id")
                        .validate(dto.getReceiveWarehouseId(), "Receive Warehouse Id");
                //行参数有效性校验
                TransactionValidate check1 = TransactionValidate.beginValidity(FndItemBase.class);
                check1.checkIdValidity(ObjectUtil.toString(dto.getItemId()), "ITEM_ID");

                check1 = TransactionValidate.beginValidity(FndWarehouse.class);
                check1.checkIdValidity(ObjectUtil.toString(dto.getReceiveWarehouseId()), "ID");

                check1 = TransactionValidate.beginValidity(FndWorker.class);
                check1.checkIdValidity(ObjectUtil.toString(dto.getReceiveWorkerId()), "ID");

                check1 = TransactionValidate.beginValidity(FndOrganizationBase.class);
                check1.checkIdValidity(ObjectUtil.toString(dto.getOrgId()), "ORGANIZATION_ID");

                //行参数数字有效性校验
                String regex = "^[a-z0-9A-Z]+$";
                if (!ObjectUtil.isNullOrEmpty(dto.getLot()) && !dto.getLot().matches(regex)) {
                    throw new LightKitsBizException(" the lot must be number or Letter");
                }
                Pattern pattern = Pattern.compile("([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9])");
                if (!pattern.matcher(dto.getReceiveQty()).matches()) {
                    throw new LightKitsBizException("The Receive Quantity is invalid");
                }
            });

        } catch (LightKitsBizException e) {
            return e.result();
        }
        return IResult.success();
    }

    /**
     * 创建送货单行数据
     *
     * @param dtos          送货单行参数
     * @param ticketId      送货单头Id
     * @param parentEventId 送货单创建事件
     * @return List<WmDeliveryTicketLine>
     */
    private CheckResult<List<WmDeliveryTicketLine>> createTicketLines(List<TicketLineDTO> dtos,
                                                                      String ticketId,
                                                                      String parentEventId) {
        CheckResult<List<WmDeliveryTicketLine>> checkResult = new CheckResult<>();
        checkResult.setSuccessful(true);
        List<WmDeliveryTicketLine> lines = new ArrayList<>();
        dtos.forEach(dto -> {
            WmDeliveryTicketLine line = new WmDeliveryTicketLine();
            line.setTicketId(ParseUtil.tryLongWithException(ticketId));
            line.setItemId(ParseUtil.tryLongWithException(dto.getItemId()));
            line.setUom(dto.getUomCode());
            line.setReceivedQty(new BigDecimal(dto.getReceiveQty()));
            line.setInventoryQty(new BigDecimal(
                    ObjectUtil.isNullOrEmpty(dto.getInventoryQty()) ? "0" : dto.getInventoryQty()));
            line.setQcNgQty(new BigDecimal(
                    ObjectUtil.isNullOrEmpty(dto.getQcNgQty()) ? "0" : dto.getQcNgQty()));
            line.setReturnedQty(new BigDecimal(
                    ObjectUtil.isNullOrEmpty(dto.getReturnQty()) ? "0" : dto.getReturnQty()));
            line.setDeliveryQty(new BigDecimal(
                    ObjectUtil.isNullOrEmpty(dto.getReceiveQty()) ? "0" : dto.getReceiveQty()));

            line.setLotCode(dto.getLot());
            line.setReceiveWarehouseId(ParseUtil.tryLongWithException(dto.getReceiveWarehouseId()));
            if (!ObjectUtil.isNullOrEmpty(dto.getReceiveWmArea())) {
                line.setReceiveWmAreaId(ParseUtil.tryLongWithException(dto.getReceiveWmArea()));
            }
            if (!ObjectUtil.isNullOrEmpty(dto.getInventoryWarehouseId())) {
                line.setInventoryWarehouseId(ParseUtil.tryLongWithException(dto.getInventoryWarehouseId()));
            }
            if (!ObjectUtil.isNullOrEmpty(dto.getInventoryWmAreaId())) {
                line.setInventoryWmAreaId(ParseUtil.tryLongWithException(dto.getInventoryWmAreaId()));
            }
            if (!ObjectUtil.isNullOrEmpty(dto.getPoId())) {
                line.setPoId(ParseUtil.tryLongWithException(dto.getPoId()));
            }
            if (!ObjectUtil.isNullOrEmpty(dto.getPoLineId())) {
                line.setPoLineId(ParseUtil.tryLongWithException(dto.getPoLineId()));
            }
            line.setDemandDate(new Date());
            line.setActualArrivalTime(new Date());
            //送货单中将图片列表转换为json格式的数据进行存储
            if (!ObjectUtil.isNullOrEmpty(dto.getPictureIds())) {
                LineControl lineControl = new LineControl();
                lineControl.setPictureIds(dto.getPictureIds());
                line.setLineControl(JsonUtil.toString(lineControl));
            }
            line.setRemark(dto.getRemark());

            //变更现有量，杂项调整，增加现有量
            List<MiscellAdjust> params = new ArrayList<>();
            MiscellAdjust param = this.createMiscell(dto, ticketId, parentEventId);
            params.add(param);
            line.store(params);
            lines.add(line);

        });
        checkResult.setData(lines);
        return checkResult;
    }

    /**
     * 杂项调整参数创建(调整为转入)
     *
     * @param dto           送货单行参数
     * @param ticketId      送货单头Id
     * @param parentEventId 送货单创建事件
     * @return MiscellAdjust
     */
    private MiscellAdjust createMiscell(TicketLineDTO dto, String ticketId, String parentEventId) {
        MiscellAdjust params = new MiscellAdjust();
        params.setTransferQty(dto.getReceiveQty());
        //所有者类型默认为"OWN"
        params.setOwnerType("OWN");
        params.setParentEventId(parentEventId);
        params.setMoveTypeCode(dto.getMoveTypeCode());
        params.setItemId(dto.getItemId());
        params.setWarehouseId(dto.getReceiveWarehouseId());
        if (!ObjectUtil.isNullOrEmpty(dto.getReceiveWmArea())) {
            params.setWmAreaId(dto.getReceiveWmArea());
        }
        params.setEventRequestId(dto.getEventRequestId());
        params.setDocumentId(ticketId);
        WmDeliveryTicket head = new WmDeliveryTicket().selectById(ticketId);
        FndDocumentTypeBase document = new FndDocumentTypeBase().selectOne(new EntityWrapper()
                .eq(FndDocumentTypeBase.DOCUMENT_TYPE_CODE, "WM_DELIVERY_TICKET"));
        params.setDocumentNum(head.getTicketNum());
        params.setDocumentTypeCode(document.getDocumentTypeCode());
        params.setDocumentTypeId(document.getId().toString());
//            params.setLot(dto.getLot());
        params.setOrgId(dto.getOrgId());
        params.setWorkerId(dto.getReceiveWorkerId());
        //调整方向
        params.setDirection("IN");
        params.setUomCode(dto.getUomCode());
        return params;
    }

    /**
     * 送货单行创建
     *
     * @param dtos          送货单行参数
     * @param ticketId      送货单头Id
     * @param parentEventId 送货单创建事件
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResult saveTicketLine(List<TicketLineDTO> dtos, String ticketId, String parentEventId) {
        //参数校验
        IResult result = this.checkParams(dtos, ticketId);
        if (!result.isSuccessful()) {
            return result;
        }
        //创建送货单行
        CheckResult<List<WmDeliveryTicketLine>> checkResult = this.createTicketLines(dtos, ticketId, parentEventId);
        if (!checkResult.isSuccessful() || ObjectUtil.isNullOrEmpty(checkResult.getData())) {
            return checkResult;
        }
        List<WmDeliveryTicketLine> lines = checkResult.getData();
        boolean linesFlag = wmDeliveyTicketLineService.insertBatch(lines);
        if (!linesFlag) {
            throw new LightKitsBizException("Save Ticket Lines Error");
        }
        //创建杂项调整参数
        lines.forEach(line -> {
            List<MiscellAdjust> params = new ArrayList<>();
            List<Object> onhandParams = line.take();
            for (Object object : onhandParams) {
                if (object.getClass().equals(MiscellAdjust.class)) {
                    MiscellAdjust record = (MiscellAdjust) object;
                    params.add(record);
                }
            }
            MiscellAdjust miscellAdjust = params.get(0);
            IResult result1 = miscellAdjustDomain.misCellAdjust(miscellAdjust);
            if (!result1.isSuccessful()) {
                throw new LightKitsBizException(result1.getMessage());
            }

        });

        return IResult.success();
    }
}
